﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using Cubicle.Core.Interfaces;
using Cubicle.Core.Processors.Parameter;
using Cubicle.Core.Shared;

namespace Cubicle.Core.Processors.Construct
{
    [Export("Cubicle.Processors.Construct.ListConstructProcessor", typeof(IProcessor<InstructionRequest>))]
    [ExportMetadata("Name", "ListConstructProcessor")]
    [ExportMetadata("Description", "Creates instances of System.Collections.Generic.List`1")]
    public class ListConstructProcessor : InstructionRequestProcessor
    {
        [Import]
        private ParameterProcessor _parameterProcessor = null;

        private static Type _listType = typeof (List<>);

        [ImportingConstructor]
        public ListConstructProcessor() : base(RequestType.CustomConstruct) { }

        #region Overrides of Processor<InstructionRequest>

        public override bool Condition(InstructionRequest request)
        {
            return base.Condition(request)
                && request.TargetType != null
                && request.TargetType.IsGenericType
                && request.TargetType.GetGenericTypeDefinition() == _listType;
        }

        public override InstructionRequest ConditionalProcess(InstructionRequest request)
        {
            var type = request.TargetType;
            var parameters = request.Inst.Parameters;
            if (type.IsGenericTypeDefinition)
            {
                var arg = TypeCache.GetType(request.Inst.ClassArgs[0]);
                type = type.MakeGenericType(new[] {arg});
            }
            var result = type.GetConstructor(new Type[0]).Invoke(null) as IList;
            var targetType = type.GetGenericArguments()[0];
            foreach (var item in parameters)
            {
                var parRequest = new ParameterRequest(targetType, item);
                _parameterProcessor.Process(parRequest);
                result.Add(parRequest.Result);
            }
            request.Complete(result);
            return request;
        }

        #endregion
    }
}